package com.ericsson.enap.modules.cdr.task;

import com.ericsson.common.quartz.task.ManualTask;
import com.ericsson.common.util.CommonUtils;
import com.ericsson.common.util.FileUtil;
import com.ericsson.common.util.LogFileName;
import com.ericsson.common.util.LoggerUtils;
import com.ericsson.enap.modules.sys.entity.EpcDict;
import com.ericsson.enap.modules.sys.service.EpcDictService;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

/**
 * @author zhuguangrui
 */
@Component
public class EnipSplitFileTask implements ManualTask {

    private final Logger log = LoggerUtils.Logger(LogFileName.EnipSplitFileJob);

    private static final String LUA_WORK = "luawork";
    private static final String LUA_DONE = "luadone";
    //((\d{3}[1-9]|\d{2}[1-9]\d|\d[1-9]\d{2}|[1-9]\d{3})(((0[13578]|1[02])(0[1-9]|[12]\d|3[01]))|((0[469]|11)(0[1-9]|[12]\d|30))|(02(0[1-9]|[1]\d|2[0-8]))))|(((\d{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229)
    //\d{4}[\-\/\s]?((((0[13578])|(1[02]))[\-\/\s]?(([0-2][0-9])|(3[01])))|(((0[469])|(11))[\-\/\s]?(([0-2][0-9])|(30)))|(02[\-\/\s]?[0-2][0-9]))
    private static final String FILE_NAME_REG = "\\d{4}[\\-\\/\\s]?((((0[13578])|(1[02]))[\\-\\/\\s]?(([0-2][0-9])|(3[01])))|(((0[469])|(11))[\\-\\/\\s]?(([0-2][0-9])|(30)))|(02[\\-\\/\\s]?[0-2][0-9]))";


    @Value("${baseDir}")
    private String baseDir;
    @Value("${cdrDataDir}")
    private String cdrDataDir;
    @Value("${downloadDir}")
    private String downloadDir;
    @Value("${fileDoneDir}")
    private String fileDoneDir;
    @Value("${splitScriptName}")
    private String splitScriptName;
    @Autowired
    private EpcDictService epcDictService;

    @Override
    public void execute() {
        log.info("==============EnipSplitFileTask start================");
        long start = System.currentTimeMillis();
        boolean luaIsRunning = this.checkProcessCount("ps -ef |grep cdr_extract", "/opt/Ericsson/core/bin/cdr_extract");
        boolean cdrSplitIsRunning = this.checkProcessCount("ps -ef |grep " + splitScriptName, "/opt/Ericsson/core/bin/" + splitScriptName);
        if (!luaIsRunning && !cdrSplitIsRunning) {

            if(this.fileDoneDir.contains("ims")){
                //1.移动目录至lua工作目录
                mvFilesToLuaWork();
                //2.定位话单下载目录，遍历文件逐个执行lua脚本写入新文件
                execLuaScript();
                //3.移动文件至imscdrfiledone/src目录并删除luadone目录下的文件
                mvFilesToSrc(this.baseDir + File.separator + this.cdrDataDir + File.separator + LUA_DONE + File.separator);
            }else{
                mvFilesToSrc(this.baseDir + File.separator + this.cdrDataDir + File.separator + this.downloadDir + File.separator);
            }

        }
        log.info("==============EnipSplitFileTask=====end  all finish use time " + (System.currentTimeMillis() - start) / 1000 + "s");
    }

    /**
     * 0.检测脚本进程数，是否在运行中
     *
     * @return true 脚本进程存在
     */
    private boolean checkProcessCount(String command, String processName) {
        boolean isRunning = false;
        Process proc;
        String[] cmd = new String[3];
        cmd[0] = "sh";
        cmd[1] = "-c";
        cmd[2] = command;
        log.info(cmd[2]);
        try {
            proc = Runtime.getRuntime().exec(cmd);
            BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String line;
            while ((line = br.readLine()) != null) {
                log.info(line.trim());
                if (line.trim().contains(processName)) {
                    isRunning = true;
                }
            }
            br.close();
            proc.waitFor();
            proc.destroy();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
        }
        return isRunning;
    }

    /**
     * 1.移动文件至lua工作目录
     */
    private void mvFilesToLuaWork() {
        String luaWorkPath = this.baseDir + File.separator + this.cdrDataDir + File.separator + LUA_WORK;
        FileUtil.newDirs(luaWorkPath);
        File cdrDownPath = new File(this.baseDir + File.separator + this.cdrDataDir + File.separator + this.downloadDir);
        if (cdrDownPath.exists()) {
            // 下载完成后迁移目录
            for (File subCgPath : cdrDownPath.listFiles()) {
                if (subCgPath.isDirectory()) {
                    File[] imsCdrFiles = subCgPath.listFiles();
                    log.info("==========move to lua work :current Path" + subCgPath + " file size is:" + imsCdrFiles.length);
                    for (File imsCdrFile : imsCdrFiles) {
                        FileUtil.syncMoveFile(imsCdrFile, new File(new File(luaWorkPath), imsCdrFile.getName()));
                    }
                }
            }
        } else {
            log.info("==========" + cdrDownPath + " is not found");
        }
    }

    /**
     * 1.遍历工作目录逐个执行lua脚本
     */
    private void execLuaScript() {
        long start = System.currentTimeMillis();
        File luaWorkPath = new File(this.baseDir + File.separator + this.cdrDataDir + File.separator + LUA_WORK);
        if (luaWorkPath.exists()) {
            String luaOutPath = this.baseDir + File.separator + this.cdrDataDir + File.separator + LUA_DONE;
            FileUtil.newDirs(luaOutPath);
            for (File imsCdrFile : luaWorkPath.listFiles()) {
                CommonUtils.execScriptCmd("/opt/Ericsson/core/bin/cdr_extract " + imsCdrFile.getAbsolutePath() + " " + luaOutPath + File.separator + imsCdrFile.getName(), log);
            }
            FileUtil.deleteWorkDir(luaWorkPath);
        }
        log.info("===========exec lua finish use time " + (System.currentTimeMillis() - start) / 1000 + "s");
    }

    /**
     * 2.移动文件至src目录
     */
    private void mvFilesToSrc(String rootPath) {

        Pattern pattern = Pattern.compile(FILE_NAME_REG);
        Set<String> srcPaths = new HashSet<>();
        String keyType = this.splitScriptName.contains("ebm")?"ebm":"cdr";
        String historyDays = epcDictService.selectEpcDict(new EpcDict(keyType + "SplitHistoryDays")).getKeyValue();
        //按后缀名过滤
        try (Stream<Path> paths = Files.walk(Paths.get(rootPath))) {
            paths.filter(Files::isRegularFile).forEach(path -> {
                Matcher m = pattern.matcher(path.toString());

                if(m.find()){

                    String typePath = this.fileDoneDir.contains("vgccdr")?path.getName(path.getNameCount()-3) + File.separator:"";
                    String srcPath = this.baseDir + File.separator + this.cdrDataDir + File.separator + this.fileDoneDir + File.separator + typePath.toUpperCase() + "src";
                    srcPaths.add(srcPath);
                    String filePathStr = srcPath + File.separator + m.group().replace("-","");
                    FileUtil.newDirs(filePathStr);
                    FileUtil.syncMoveFile(path.toFile(), new File(new File(filePathStr), path.toFile().getName()));
                }
            });
            for(String srcPath : srcPaths) {
                execSplitCdrScript(srcPath);
                FileUtil.deleteExpireDirs(new File(srcPath.replace("src","desc")), "yyyyMMdd", Integer.parseInt(historyDays), log);
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.error("==========IOException:" + e.getMessage(),e);
        }
    }

    /**
     * 3.执行split_cdr脚本
     */
    public void execSplitCdrScript(String srcPath) {
        log.info("exectureScript ===============  split_cdr start");
        long start = System.currentTimeMillis();
        File srcDir = new File(srcPath);
        FileUtil.deleteExpireDirs(srcDir,"yyyyMMdd",2,log);
        String localWorkFolder = srcPath.replace("src","work");
        FileUtil.newDirs(localWorkFolder);
        for (File dateDir : srcDir.listFiles()) {
            String descFolder = srcPath.replace("src","desc") + File.separator + dateDir.getName();
            FileUtil.newDirs(new File(descFolder));
            if (dateDir.exists()) {
                batchExecuteScript(localWorkFolder, dateDir, descFolder);
            } else {
                log.info(dateDir + " not exists");
            }
        }

        long end = System.currentTimeMillis();
        log.info("exectureScript split finish use time " + (end - start) / 1000 + "s");
    }


    /**
     * 3.1分批执行目录中的文件，调用脚本
     *
     * @param localWorkFolder 源目录
     * @param dateDir         日期目录
     * @param descFolder      目标目录
     */
    private void batchExecuteScript(String localWorkFolder, File dateDir, String descFolder) {
        File[] files = dateDir.listFiles();
        log.info(" this files size :" + files.length);
        for (int i = 0; i < files.length; i++) {
            if (files.length > 100 && i < 100) {
                CommonUtils.fileMv(files[i].getAbsolutePath(), localWorkFolder);
            } else if (files.length <= 100) {
                CommonUtils.fileMv(files[i].getAbsolutePath(), localWorkFolder);
            }
        }
        String scriptParam = this.splitScriptName.contains("ebm")?" ebm_offset_c_amf":"";
        CommonUtils.execScriptCmd("/opt/Ericsson/core/bin/" + splitScriptName + " " + localWorkFolder + " " + descFolder + scriptParam, log);
        FileUtil.deleteWorkDir(new File(localWorkFolder));
        files = dateDir.listFiles();
        if (files != null && files.length > 0) {
            batchExecuteScript(localWorkFolder, dateDir, descFolder);
        }
    }

}
